package com.cn.nio;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;

@Slf4j
public class NioService4Client {

  public static void main(String[] args) {
    try {
      Selector selector = Selector.open();

      SocketChannel socketChannel = SocketChannel.open();
      socketChannel.configureBlocking(false);
      socketChannel.connect(new InetSocketAddress("127.0.0.1", 8080));

      socketChannel.register(selector, SelectionKey.OP_CONNECT); // SelectionKey.OP_CONNECT 这个事件只给客户端使用

      while (true) {
        selector.select();
        Set<SelectionKey> selectionKeys = selector.selectedKeys();
        log.debug("selectionKeys{}", selectionKeys);
        Iterator<SelectionKey> iterator = selectionKeys.iterator();
        while (iterator.hasNext()) {
          SelectionKey next = iterator.next();
          iterator.remove();

          if (next.isConnectable()) {
            //获取已经建立好连接的socketchannel
            SocketChannel newsocketChannel = (SocketChannel) next.channel();

            //必须调用finishConnect 建立一个连接
            while (!newsocketChannel.finishConnect()) {
              log.debug("finishConnect ...");
            }
            newsocketChannel.register(selector, SelectionKey.OP_WRITE);
          } else if (next.isWritable()) {
            SocketChannel newsocketChannel = (SocketChannel) next.channel();
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            String request = "hello world " + System.currentTimeMillis();
            System.out.println("请输入要发送的信息");
            Scanner scanner = new Scanner(System.in);
            String name = scanner.next();//接收用户输入
            request +=  " " + name;
            buffer.put(request.getBytes());
            /*
             切换成读模式,这flip()
             一定要加,因为buffer再写入channel时，就是按照 position、limit 两个指针来控制数据长度的
             position = 0
             limit = position
             */
            buffer.flip();
            newsocketChannel.write(buffer);
            log.info("发送请求");
            newsocketChannel.register(selector, SelectionKey.OP_READ,new SimpleDateFormat("yyyyMMdd HHmmss.ss").format(new Date()));
          } else if (next.isReadable()) {
            SocketChannel newsocketChannel = (SocketChannel) next.channel();
            Object attachment = next.attachment();
            log.info("print out {}",String.valueOf(attachment));
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            newsocketChannel.read(buffer);
            log.info("读取服务端响应 {}", new String(buffer.array(), StandardCharsets.UTF_8));
            //读完就关闭了
            newsocketChannel.close();
          }

        }
      }

    } catch (IOException e) {
      e.printStackTrace();
    }

  }

}
